﻿using PdfiumViewer;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;
using TestPrint.PrintNameHelp;

namespace TestPrint.PrintHelp
{
    public class PrintHelper : PrintManager
    {

        public void Print(List<OutputImage> outputImages)
        {
            var printSetting = LocalPrinterSetting.ShowUI(LocalPrinterSetting.bag, p =>
            {
                if (string.IsNullOrWhiteSpace(p.Setting.Printer))
                    p.Errors.Add("请您设置打印机！");
            });
            if (printSetting == null) return;

            foreach (var it in outputImages)
            {
                Print(it, printSetting.Printer);
            }
        }

        /// <summary>
        /// 打印
        /// </summary>
        public void Print(OutputImage outputImage, string printer)
        {
            switch (outputImage.ImageType)
            {
                case "PDF":
                    PrintPDF(outputImage, printer);
                    break;

                case "EPL":
                case "EPL2":
                    PrintEPL2(outputImage, printer);
                    break;

                case "PNG":
                case "JPG":
                    PrintPNG(outputImage, printer);
                    break;
                case "EMF":
                    PrintEMF(outputImage, printer);
                    break;
            }
        }


        /// <summary>
        /// Pdfium PNG图打印
        /// </summary>
        private void PrintPDF(OutputImage outputImage, string printer)
        {
            PrinterSettings printerSettings = new PrinterSettings();
            printerSettings.PrinterName = printer;
            PaperSize ps = new PaperSize("custom", outputImage.PageWidth, outputImage.PageHeight);
            printerSettings.DefaultPageSettings.PaperSize = ps;
            foreach (var file in outputImage.Images)
            {
                using (var stream = new MemoryStream(file))
                {
                    var pdfDocument = PdfDocument.Load(stream);
                    for (int pageIndex = 0; pageIndex < pdfDocument.PageCount; pageIndex++)
                    {
                        PrintPage(outputImage.ImageType, printerSettings, (obj, ev) =>
                        {
                            var dpiX = ev.Graphics.DpiX;
                            var dpiY = ev.Graphics.DpiY;
                            var printableArea = ev.PageSettings.PrintableArea; //获取打印区域大小

                            if (outputImage.use_metadata)
                            {
                                //使用元数据打印
                                Rectangle PrintableRectangle = new Rectangle(
                                                   0,
                                                   0,
                                                   (int)(dpiX / 100.0 * printableArea.Width),
                                                   (int)(dpiY / 100.0 * printableArea.Height));
                                pdfDocument.Render(pageIndex, ev.Graphics, dpiX, dpiY, PrintableRectangle, PdfRenderFlags.ForPrinting | PdfRenderFlags.Annotations);
                            }
                            else
                            {
                                //使用图片打印
                                var pageSize = pdfDocument.PageSizes[pageIndex];
                                var num1 = 600 / pageSize.Width;
                                var num2 = 600 / pageSize.Height;
                                var sx = (num1 < num2) ? num1 : num2;
                                int width, height;
                                if (sx < 1)
                                {
                                    width = AdjustDpi(pageSize.Width * sx);
                                    height = AdjustDpi(pageSize.Height * sx);
                                }
                                else
                                {
                                    width = AdjustDpi(pageSize.Width);
                                    height = AdjustDpi(pageSize.Height);
                                }
                                using (var image = pdfDocument.Render(pageIndex, width, height, dpiX, dpiY, false))
                                {
                                    RectangleF printableRectangleF = new RectangleF(0F, 0F, printableArea.Width, printableArea.Height);
                                    ev.Graphics.DrawImage(image, printableRectangleF);
                                }
                            }
                            ev.Graphics.Dispose();
                            //GC.WaitForPendingFinalizers();
                        });
                    }
                }
            }
        }

        private static int AdjustDpi(double value)
        {
            return (int)((value / 72f) * 600f);
        }

        private void PrintEPL2(OutputImage outputImage, string printer)
        {
            PrinterSettings printerSettings = new PrinterSettings();
            printerSettings.PrinterName = printer;
            PaperSize ps = new PaperSize("custom", outputImage.PageWidth, outputImage.PageHeight);
            printerSettings.DefaultPageSettings.PaperSize = ps;
            foreach (var file in outputImage.Images)
            {
                PrintPage(outputImage.ImageType, printerSettings, (obj, ev) =>
                {
                    WritePageBytes(file);
                });
            }
        }

        private void PrintPNG(OutputImage outputImage, string printer)
        {
            PrinterSettings printerSettings = new PrinterSettings();
            printerSettings.PrinterName = printer;
            PaperSize ps = new PaperSize("custom", outputImage.PageWidth, outputImage.PageHeight);
            printerSettings.DefaultPageSettings.PaperSize = ps;
            foreach (var file in outputImage.Images)
            {
                PrintPage(outputImage.ImageType, printerSettings, (obj, ev) =>
                {
                    using (var stream = new MemoryStream(file))
                    {
                        var pageSize = ev.PageSettings.PrintableArea; //获取打印区域大小
                        System.Drawing.Rectangle PrintableRectangle = new System.Drawing.Rectangle(
                        0,
                        0,
                        (int)pageSize.Width,
                        (int)pageSize.Height);
                        ev.Graphics.DrawImage(Image.FromStream(stream), PrintableRectangle);
                        GC.WaitForPendingFinalizers();
                    }
                });
            }
        }

        private void PrintEMF(OutputImage outputImage, string printer)
        {
            PrinterSettings printerSettings = new PrinterSettings();
            printerSettings.PrinterName = printer;
            PaperSize ps = new PaperSize("custom", outputImage.PageWidth, outputImage.PageHeight);
            printerSettings.DefaultPageSettings.PaperSize = ps;

            foreach (var file in outputImage.Images)
            {
                PrintPage(outputImage.ImageType, printerSettings, (obj, ev) =>
                {
                    var bytes = MetaFile.Play(file);
                    using (var stream = new MemoryStream(bytes))
                    {
                        Metafile image = new Metafile(stream);
                        var pageSize = ev.PageSettings.PrintableArea; //获取打印区域大小
                        System.Drawing.Rectangle PrintableRectangle = new System.Drawing.Rectangle(
                            0,
                            0,
                            (int)pageSize.Width,
                            (int)pageSize.Height);
                        ev.Graphics.DrawImage(image, PrintableRectangle);
                        GC.WaitForPendingFinalizers();
                    }
                });
            }
        }
    }

    public class OutputImage
    {
        public string ImageType { get; set; }
        public bool use_metadata { get; set; }
        public int PageWidth { get; set; }
        public int PageHeight { get; set; }
        public List<byte[]> Images { get; set; }
    }
}
